package dk.fuddi.grails

import grails.converters.JSON
import org.springframework.beans.factory.InitializingBean

class EarthquakeService implements InitializingBean {

  static transactional = true

  String url = "http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.xml"
  Date latestFetchEarthquakes
  def flotJSONDataList

  def getEarthquakes() {
    log.info "Get earthquakes xml from url [$url]"
    def xml = url.toURL().text
    def rss = new XmlSlurper().parseText(xml)
    List<Earthquake> eqList = new ArrayList<Earthquake>()
    rss.entry.each {
      Earthquake eq = new Earthquake()
      eq.name = it.id

      String title = it.title
      def index = title.indexOf(",")
      String magnitude = title.substring(0, index).substring(2)
      assert magnitude.isDouble()
      eq.magnitude = magnitude.toDouble()
      eq.title = title.substring(index + 1).trim()

      eq.updated = it.updated

      String point = it.point
      def points = point.split(" ")
      assert points.length == 2
      eq.lat = points[0].toDouble()
      eq.lng = points[1].toDouble()

      eqList.add eq
    }

    latestFetchEarthquakes = new Date()
    log.info "Fetch " + eqList.size() + " earthquakes"

    return eqList
  }

  class FlotSeriesData {
    String name
    int count
    float percent

    FlotSeriesData(String name) {
      this.name = name
    }
  }

  class FlotSeriesName {
    String name
    double minMag
    double maxMag

    FlotSeriesName(String name, double minMag, double maxMag) {
      this.name = name
      this.minMag = minMag
      this.maxMag = maxMag
    }
  }

  public static final String[] flotSeriesName = ['Weak 2.9 or less', 'Minor 3-3.9', 'Light 4-4.9', 'Moderate 5-5.9',
      'Strong 6-6.9', 'Major 7-7.9', 'Great 8 or more']
  public static final Map<String, FlotSeriesName> flotSeriesNameMap = new HashMap<String, FlotSeriesName>()

  void afterPropertiesSet() {
    flotSeriesNameMap.put(flotSeriesName[0], new FlotSeriesName(flotSeriesName[0], 0, 2.9))
    flotSeriesNameMap.put(flotSeriesName[1], new FlotSeriesName(flotSeriesName[1], 3, 3.9))
    flotSeriesNameMap.put(flotSeriesName[2], new FlotSeriesName(flotSeriesName[2], 4, 4.9))
    flotSeriesNameMap.put(flotSeriesName[3], new FlotSeriesName(flotSeriesName[3], 5, 5.9))
    flotSeriesNameMap.put(flotSeriesName[4], new FlotSeriesName(flotSeriesName[4], 6, 6.9))
    flotSeriesNameMap.put(flotSeriesName[5], new FlotSeriesName(flotSeriesName[5], 7, 7.9))
    flotSeriesNameMap.put(flotSeriesName[6], new FlotSeriesName(flotSeriesName[6], 8, 100))
  }

  def getFlotJSONDataList() {
    if (flotJSONDataList == null) {
      updateFlotJSONData()
    }
    flotJSONDataList
  }

  def updateFlotJSONData() {
    log.info "Update flot JSON data"

    def flotDataMap = new HashMap<String, FlotSeriesData>()
    for (int i = 0; i < flotSeriesName.length; i++) {
      def fd = new FlotSeriesData(flotSeriesName[i])
      flotDataMap.put(fd.name, fd)
    }

    def earthquakes = Earthquake.list()
    for (eq in earthquakes) {
      if (eq.magnitude <= 2.9) {
        flotDataMap.get(flotSeriesName[0]).count++
      }
      else if (eq.magnitude >= 3 && eq.magnitude <= 3.9) {
        flotDataMap.get(flotSeriesName[1]).count++
      }
      else if (eq.magnitude >= 4 && eq.magnitude <= 4.9) {
        flotDataMap.get(flotSeriesName[2]).count++
      }
      else if (eq.magnitude >= 5 && eq.magnitude <= 5.9) {
        flotDataMap.get(flotSeriesName[3]).count++
      }
      else if (eq.magnitude >= 6 && eq.magnitude <= 6.9) {
        flotDataMap.get(flotSeriesName[4]).count++
      }
      else if (eq.magnitude >= 7 && eq.magnitude <= 7.9) {
        flotDataMap.get(flotSeriesName[5]).count++
      }
      else if (eq.magnitude >= 8) {
        flotDataMap.get(flotSeriesName[6]).count++
      }
    }

    //calculate percent
    def flotSeriesDataList = flotDataMap.values()
    flotSeriesDataList.each {
      if (it.count > 0) {
        it.percent = it.count / earthquakes.size() * 100
      }
    }

    //convert to json list
    def list = flotSeriesDataList.collect {eq -> [name: eq.name, percent: eq.percent]}
    flotJSONDataList = list as JSON
  }

}
